package com.atguigu.gmall.order.controller;

import com.atguigu.gmall.cart.CartFeignClient;
import com.atguigu.gmall.common.result.Result;
import com.atguigu.gmall.common.util.AuthContextHolder;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.model.user.UserAddress;
import com.atguigu.gmall.order.service.OrderService;
import com.atguigu.gmall.user.client.UserFeignClient;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @author mqx
 * @date 2020-10-22 10:47:15
 */
@RestController
@RequestMapping("api/order")
public class OrderApiController {

    @Autowired
    private UserFeignClient userFeignClient;

    @Autowired
    private CartFeignClient cartFeignClient;

    @Autowired
    private OrderService orderService;
    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;

    //  定义远程接口
    @GetMapping("auth/trade")
    public Result trade(HttpServletRequest request) {
        String userId = AuthContextHolder.getUserId(request);
        //  需要获取到用户Id
        //  第一件事：获取到收货人的地址列表
        List<UserAddress> userAddressList = userFeignClient.findUserAddressListByUserId(userId);
        //  第二件事：获取到用户购买的商品列表
        List<CartInfo> cartCheckedList = cartFeignClient.getCartCheckedList(userId);
        //  声明一个订单明细的集合，来存储数据
        List<OrderDetail> orderDetailList = new ArrayList<>();
        //  数据渲染时，应该渲染订单明细OrderDetail.
        for (CartInfo cartInfo : cartCheckedList) {
            OrderDetail orderDetail = new OrderDetail();
            orderDetail.setSkuId(cartInfo.getSkuId());
            orderDetail.setSkuName(cartInfo.getSkuName());
            orderDetail.setImgUrl(cartInfo.getImgUrl());
            orderDetail.setSkuNum(cartInfo.getSkuNum());
            orderDetail.setOrderPrice(cartInfo.getSkuPrice());

            //  将每个orderDetail 放入集合
            orderDetailList.add(orderDetail);
        }

        //  页面需要总金额
        OrderInfo orderInfo = new OrderInfo();
        //  必须知道当前订单购买了哪些商品
        orderInfo.setOrderDetailList(orderDetailList);
        //  计算总金额
        orderInfo.sumTotalAmount();
        //  此处：跟商品详情做数据汇总一样！

        Map<String, Object> result = new HashMap<>();
        //  页面需要渲染，必须有key，此处存储的key 必须跟前台页面保存一致！
        result.put("userAddressList", userAddressList);
        result.put("detailArrayList", orderDetailList);
        //  件数：第一种理解,可以认为集合的长度，第二种：每个商品件数的总和。
        result.put("totalNum", orderDetailList.size());
        result.put("totalAmount", orderInfo.getTotalAmount());

        //  设置一个流水号
        String tradeNo = orderService.getTradeNo(userId);
        result.put("tradeNo", tradeNo);
        return Result.ok(result);
    }

    // web-all , 返回页面。trade.html ,要数据 ，获取后台存储数据，requset.add("key", result.getData());
    // web-all , 返回页面。trade.html, 如果不需要code 等。那么我们也可以返回集合。


    //  http://api.gmall.com/api/order/auth/submitOrder?tradeNo=null
    //  保存控制器   tradeNo=null tradeNo是什么呢? 页面生产的流水号。
    //  页面提交过来的是Json 字符串 ，将其变为OrderInfo 对象。
    @PostMapping("auth/submitOrder")
    public Result submitOrder(@RequestBody OrderInfo orderInfo, HttpServletRequest request) {

        //  获取用户Id
        String userId = AuthContextHolder.getUserId(request);
        //  【userId】
        orderInfo.setUserId(Long.parseLong(userId));

        //  在保存之前执行 http://api.gmall.com/api/order/auth/submitOrder?tradeNo=null
        //  获取到前台传递过来的流水号
        String tradeNo = request.getParameter("tradeNo");

        //  调用比较方法
        //  表示流水号不一致
        if (!orderService.checkTradeCode(tradeNo, userId)) {
            //  提示消息
            return Result.fail().message("不能重复提交订单！");
        }

        //  删除
        orderService.delTradeNo(userId);

        //  验证库存： 需要每个商品都进行验证 
/*        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        for (OrderDetail orderDetail : orderDetailList) {
            //  远程调用验证
            boolean res = orderService.checkStock(orderDetail.getSkuId(), orderDetail.getSkuNum());
            //  res = true 表示有库存，fasle 表示库存不足
            if (!res){
                //  提示消息
                return Result.fail().message(orderDetail.getSkuName()+"库存不足！");
            }
        }*/
        //验证库存优化
        List<String> errorList = new ArrayList<>();
        List<CompletableFuture> futureList = new ArrayList<CompletableFuture>();
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        for (OrderDetail orderDetail : orderDetailList) {
            CompletableFuture<Void> checkStockCompletableFuture = CompletableFuture.runAsync(() -> {
                boolean result = orderService.checkStock(orderDetail.getSkuId(), orderDetail.getSkuNum());
                if (!result) {
                    errorList.add(orderDetail.getSkuName() + "库存不足!");
                }
            }, threadPoolExecutor);
            futureList.add(checkStockCompletableFuture);
        }
        //合并线程
        CompletableFuture.allOf(futureList.toArray(new CompletableFuture[futureList.size()])).join();
        if(errorList.size()>0){
            return Result.fail().message(StringUtils.join(errorList,","));
        }

        // 调用保存方法
        Long orderId = orderService.saveOrderInfo(orderInfo);

        return Result.ok(orderId);
    }

    /**
     * 内部调用获取订单
     * @param orderId
     * @return
     */
    @GetMapping("inner/getOrderInfo/{orderId}")
    public OrderInfo getOrderInfo(@PathVariable(value = "orderId") Long orderId) {
        return orderService.getOrderInfo(orderId);
    }
}
